package com.syf.kit;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.syf.core.kit.SyFrameKit;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SyFrameKit("默认的jackson中jsonMapper")
public class SyfJsonMapper {
    private ObjectMapper objectMapper;

    public SyfJsonMapper(boolean isIgnoreNull, boolean isIgnoreUnknownFields) {
        this.objectMapper = new ObjectMapper();

        if (isIgnoreNull) {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //在序列化时忽略值为 null 的属性
        }

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
        // 在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ ,比如如果一个类中有private Date date;这种日期属性，序列化后为：{"date" : 1413800730456}，若不为true，则为{"date" : "2014-10-20T10:26:06.604+0000"}
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 允许序列化空的POJO类
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 把java.util.Date, Calendar输出为数字(时间戳)
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 在遇到未知属性的时候不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        objectMapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, isIgnoreUnknownFields);
    }

    public SyfJsonMapper(SerializationConfig serializationConfig, DeserializationConfig deserializationConfig) {
        this.objectMapper = new ObjectMapper();

        objectMapper.setConfig(serializationConfig);
        objectMapper.setConfig(deserializationConfig);
    }

    public SyfJsonMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public String toJsonString(Map<String, Object> dataMap) {
        try {
            return objectMapper.writeValueAsString(dataMap);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Map<String,Object>转json字符串出现异常", e);
        }
    }

    public String toJsonString(Object beanObj) {
        try {
            return objectMapper.writeValueAsString(beanObj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("bean object转json字符串出现异常", e);
        }
    }

    public Map<String, Object> toHashMap(String jsonString) {
        return toHashMap(jsonString, String.class, Object.class);
    }

    public <K, V> Map<K, V> toHashMap(String jsonString, Class<K> keyClass, Class<V> valueClazz) {
        try {
            return objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructMapType(HashMap.class, keyClass, valueClazz));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json字符串转HashMap<" + keyClass.getName() + "," + valueClazz.getName() + ">出现异常", e);
        }
    }

    public <E> List<E> toList(String jsonString, Class<E> elementClass) {
        try {
            return objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, elementClass));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json字符串转List<" + elementClass.getName() + ">出现异常", e);
        }
    }

    public <T> T toBean(String jsonString, Class<T> beanClass) {
        try {
            return objectMapper.readValue(jsonString, beanClass);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json字符串转bean[" + beanClass.getName() + "]出现异常", e);
        }
    }

    /**
     * @param jsonString
     * @param beanClass      bean类
     * @param typeRefClasses bean类的泛型数组
     */
    public <T> T toBean(String jsonString, Class<T> beanClass, Class<?>... typeRefClasses) {
        try {
            return objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructParametricType(beanClass, typeRefClasses));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json字符串转bean[" + beanClass.getName() + "]出现异常", e);
        }
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }
}
